На главную страницу


View in English


Как написать службу NT на VB6/VB5

Как известно, Visual Basic - не самое подходящее средство для написания служб (Service) Windows NT/2000/XP. Проблема заключается в том, что для написания службы требуется использование функции API CreateThread, что не поддерживается ни VB5, ни VB6. VB позволяет создавать многопоточные программы, но не с помощью функции CreateThread. VB5 использует общий объект Err для всех потоков, созданных функцией API CreateThread. Это недопустимо, поскольку изменение значений этого объекта может происходить из разных потоков в непредсказуемой последовательности и даже одновременно на многопроцессорных компьютерах. Напротив, VB6 использует для объекта Err (и не только для него) локальную память потока (TLS), но в момент создания потока функцией CreateThread TLS не инициализирована, и поэтому после простой перекомпиляции в VB6 программа не работает совсем (точнее, работает только при компиляции в p-code с общим объектом Err).

Довольно сложный способ решения проблемы создания потоков в VB предложил Мэтью Кэрланд (см. ссылки), но для создания службы можно применить более простое решение. Программа будет работать и без TLS, если в новом потоке совсем не использовать объект Err, а кроме этого использовать только арифметические операторы и вызовы API, описанные в библиотеке типов. Как известно, свойства объекта Err обновляются в двух случаях: когда происходит Run-time ошибка (Err.Number), и после выполнения каждой функции API (Err.LastDllError). Первого можно избежать написанием безошибочного кода, второго - описанием функций API с помощью библиотеки типов (описание функций API не должно содержать атрибутов usesgetlasterror, поэтому библиотеки типов из известной книги Брюса Мак-Кинни не годятся). Функциональная часть службы должна работать в главном потоке, и на нее указанные ограничения не распространяются. Этот подход работает как в VB6, так и в VB5.

Разумеется, для создания своей службы вы можете использовать бесплатный элемент управления NTSVC.OCX от Microsoft, и этот способ достаточно прост и надежен, но имеет один недостаток: вы не можете применять опцию "Unattended execution". Совместно с этой опцией элементы управления OCX применяться не могут, а именно такой режим работы для службы является предпочтительным. Кроме того, поскольку этот элемент управления распространяется в виде исходного кода, существует несколько откомпилированных версий этого компонента, не вполне совместимых между собой.

Этот пример написан при помощи VB6 без использования каких-либо внешних компонентов. Поскольку служба скомпилирована с опцией "Unattended execution", она не имеет визуального интерфейса. Для просмотра сообщений, записываемых службой в Application Log, используйте Event Viewer.

Функциональная часть службы (отсутствующая в данном примере) должна управляться событиями, поступающими от Диспетчера Служб. Все события должны обрабатываться в течение нескольких секунд, в противном случае служба не будет иметь возможности обрабатывать запросы Диспетчера Служб.

См. также:

Microsoft Knowledge Base Q137890, Q170883, Q175948,

An OLE Control for Creating Win32 Services in Visual Basic,

Manipulate Windows NT Services by Writing a Service Control Program,

Creating an Agent NT Service with VB,

How-To Run Your Application as a Service,

How-To Run Your Application as a Service - Part II,

Статью Мэтью Кэрланда "Create Worker Threads in DLLs" в журнале "Visual Basic Programmer's Journal" за июнь 1999 года.

Загрузить исходный код
vb6svc.zip (32 кБ, интерфейс на английском языке)

Эта страница обновлялась в последний раз 25 фев 2002 г.
© 2002 Сергей Мерзликин
Пишите: